import axios from 'axios'
import {message} from 'ant-design-vue'
import store from '../store/index'

const defaultInstance = getInstance()

// 异常拦截处理器
const errorHandler = (error) => {
    const response = error.response
    message.error('请求失败')
    if (response.status === 401) {
        // 清空本地Token并跳转登陆页面
        localStorage.clear()
        message.error('Token已过期，请重新登陆')
        setTimeout(() => {
            window.location.replace(window.location.origin)
        }, 2000)
    } else {
        // 对返回的错误信息进行处理，例如输出错误日志或者发送错误报告等
        console.error(error)
        return Promise.reject(error)
    }
}

function defaultRequestSuccessFn(config) {
    return addAuthorizationHeader(config)
}

function addAuthorizationHeader(config) {
    const token = localStorage.getItem('token')
    if (token) {
        config.headers.Authorization = `Bearer ${token}`
    }
    return config
}

function defaultRequestErrorFn(error) {
    return errorHandler(error)
}

function defaultResponseSuccessFn(response) {
    const {isShowSuccessMessage} = response.config || {}
    const code = response.data.code
    if (code === 200) {
        if (isShowSuccessMessage) {
            message.success(response.data.message || '操作成功')
        }
        const {responseType} = response.config
        if (responseType === 'Blob') {
            return response
        } else {
            return response.data
        }
    } else {
        message.error(response.data.message || '请求失败')
        return Promise.reject(response.data)
    }
}

function defaultResponseErrorFn(error) {
    return errorHandler(error)
}

function openLoading() {
    store.dispatch('common/showLoading')
}

function closeLoading() {
    store.dispatch('common/hideLoading')
}

// 提供默认拦截器，支持传入自定义拦截器
// 增加loading 和 timeout处理
// 增加并发处理 和 错误重试机制（优化版，自己理解）
export function getInstance(config = {}) {
    // 请求队列，每个元素包含一个请求的配置和回调函数
    const requestQueue = [];

    // 最大并发请求数量
    const maxConcurrentRequests = 5;

    // 是否启动
    let isRun = false
    const {baseURL, timeout, requestSuccessFn, requestErrorFn, responseSuccessFn, responseErrorFn} = config

    const service = axios.create({
        baseURL: baseURL || '/api',
        timeout: timeout || 30000
    })

    service.interceptors.request.use(
        async (config) => {
            if (typeof requestSuccessFn === 'function') {
                return await requestSuccessFn(config)
            } else {
                return await defaultRequestSuccessFn(config)
            }
        },
        async (error) => {
            closeLoading()

            if (typeof requestErrorFn === 'function') {
                return await requestErrorFn(error)
            } else {
                return await defaultRequestErrorFn(error)
            }
        }
    )

    service.interceptors.response.use(
        async (response) => {
            if (requestQueue.length === 0) {
                closeLoading()
            }

            // 如果还有未处理的请求，继续发送请求
            if (requestQueue.length > 0) {
                const nextRequest = requestQueue.shift();
                sendRequest(nextRequest.config, nextRequest.callback);
            }

            if (typeof responseSuccessFn === 'function') {
                return await responseSuccessFn(response)
            } else {
                return await defaultResponseSuccessFn(response)
            }
        },
        async (error) => {
            closeLoading()

            if (typeof responseErrorFn === 'function') {
                return await responseErrorFn(error)
            } else {
                return await defaultResponseErrorFn(error)
            }
        }
    )

    // 发送请求的函数
    const sendRequest = (config, callback, retryCount = 0) => {
        service(config)
            .then((response) => {
                // 请求成功，执行回调函数
                callback(response);
            })
            .catch((error) => {
                // 请求失败，重试
                if (retryCount < 3) {
                    console.log(`Request failed, retrying (${retryCount + 1})...`);
                    sendRequest(config, callback, retryCount + 1);
                } else {
                    console.log(`Request failed after ${retryCount} retries.`);
                }
            });
    };

    const run = () => {
        for (let i = 0; i < maxConcurrentRequests; i++) {
            const nextRequest = requestQueue.shift();
            nextRequest && sendRequest(nextRequest.config, nextRequest.callback);
        }
    }

    // 重写axiosInstance方法
    const axiosInstanceWithQueue = (config) => {
        return new Promise((resolve, reject) => {
            const {loading} = config

            if (loading && requestQueue.length === 0) {
                openLoading()
            }

            requestQueue.push({
                config: config,
                callback: (response) => {
                    resolve(response);
                }
            });

            if (!isRun) {
                isRun = true
                Promise.resolve(true).then(() => {
                    run()
                })
            }
        });
    };

    return axiosInstanceWithQueue
}

export default defaultInstance